/*
 * Copyright (C) 2011-2015 ShenZhen iBOXPAY Information Technology Co.,Ltd.
 * 
 * All right reserved.
 * 
 * This software is the confidential and proprietary
 * information of iBoxPay Company of China. 
 * ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only
 * in accordance with the terms of the contract agreement 
 * you entered into with iBoxpay inc.
 *
 */

package com.iboxpay.sdk;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

import org.apache.commons.lang.StringUtils;

import com.iboxpay.sdk.Coder.Padding;

/**
 * The class Des3Coder.
 *
 * Description: 
 *
 * @author: nieminjie
 * @since: 2016年2月29日	
 * @version: $Revision$ $Date$ $LastChangedBy$
 *
 */

public class Des3Coder {

	public final static Charset UTF_8 = Charset.forName("UTF-8");

	/**
	 * ECB/PKCS5模式加密
	 * @param data
	 * @param key
	 * @param chiperAlgorithm
	 * @return
	 */
	public static byte[] encrypt(byte[] data, byte[] key) {
		return encrypt(data, key, Mode.ECB, Padding.PKCS5Padding);
	}

	/**
	 * 定义分组与填充模式加密
	 * @param data
	 * 					原文字节数组
	 * 
	 * @param key
	 * 					密钥字节数组
	 * 
	 * @param mode
	 * 					分组模式 @see com.iboxpay.frmw.algo.Coder.Mode
	 * 
	 * @param padding
	 * 					填充模式 @see com.iboxpay.frmw.algo.Coder.Padding
	 * 
	 * @return
	 */
	public static byte[] encrypt(byte[] data, byte[] key, String mode, String padding) {
		return Coder.encrypt(data, key, Coder.DES3_KEY_ALGORITHM, mode, padding);
	}

	/**
	 * ECB/PKCS5模式加密
	 * @param data
	 * 					原文
	 * 
	 * @param key
	 * 					密钥
	 * 
	 * @return
	 */
	public static String encrypt(String data, String key) {

		//执行操作
		return encrypt(data, key, Mode.ECB, Padding.PKCS5Padding);
	}

	/**
	 * 定义模式加密
	 * @param data
	 * 					原文
	 * 
	 * @param key
	 * 					密钥
	 * 
	 * @param mode
	 * 					分组模式 @see com.iboxpay.frmw.algo.Coder.Mode
	 * 
	 * @param padding
	 * 					填充模式 @see com.iboxpay.frmw.algo.Coder.Padding
	 * @return
	 */
	public static String encrypt(String data, String key, String mode, String padding) {

		//执行操作
		return EncodeUtil.bytesToHexString(encrypt(data.getBytes(UTF_8), key.getBytes(UTF_8), mode, padding));
	}

	/**
	 * ECB/PKCS5模式解密
	 * @param data
	 * @param key
	 * @param chiperAlgorithm
	 * @return
	 */
	public static byte[] decrypt(byte[] data, byte[] key) {
		return decrypt(data, key, Mode.ECB, Padding.PKCS5Padding);
	}

	/**
	 * 定义模式解密
	 * @param data
	 * 					密文字节数组
	 * 
	 * @param key
	 * 					密钥字节数组
	 * 
	 * @param mode
	 * 					分组模式 @see com.iboxpay.frmw.algo.Coder.Mode
	 * 
	 * @param padding
	 * 					填充模式 @see com.iboxpay.frmw.algo.Coder.Padding
	 * @return
	 */
	public static byte[] decrypt(byte[] data, byte[] key, String mode, String padding) {
		return Coder.decrypt(data, key, Coder.DES3_KEY_ALGORITHM, mode, padding);
	}

	/**
	 * ECB/PKCS5模式解密
	 * @param data
	 * @param key
	 * @param chiperAlgorithm
	 * @return
	 */
	public static String decrypt(String data, String key) {
		return decrypt(data, key, Mode.ECB, Padding.PKCS5Padding);
	}

	/**
	 * ECB/PKCS5模式解密
	 * @param data
	 * @param key
	 * @param chiperAlgorithm
	 * @return
	 */
	public static String decrypt(String data, String key, String mode, String padding) {
		if (StringUtils.isBlank(data)) {
			return "";
		}
		return new String(decrypt(EncodeUtil.hexStringToByte(data), key.getBytes(UTF_8), mode, padding));
	}

	public static void main(String[] args) throws UnsupportedEncodingException {
		String key = "=nv[A6jMzwevG4od";
		String encrypt = encrypt("621785******5330", key, Mode.ECB, Padding.NoPadding);
		System.out.println(encrypt);
		System.out.println(decrypt(encrypt, key, Mode.ECB, Padding.NoPadding));
	}

	/**
	 * 离散密钥
	 * @param random
	 * @param key
	 * @return
	 */
	public static byte[] disperse(byte[] factor, byte[] key) {
		if (factor == null || factor.length != 8) {
			throw new IllegalArgumentException(" factor length is not 8 bytes.");
		}
		byte[] firstBytes = new byte[8];
		byte[] secondBytes = new byte[8];
		byte[] ret = new byte[16];
		System.arraycopy(factor, 0, firstBytes, 0, 8);
		for (int i = 0; i < 8; i++) {
			secondBytes[i] = (byte) ~factor[i];
		}
		firstBytes = encrypt(firstBytes, key);
		secondBytes = encrypt(secondBytes, key);
		System.arraycopy(firstBytes, 0, ret, 0, 8);
		System.arraycopy(secondBytes, 0, ret, 8, 8);

		return ret;
	}

	/**
	 * 3DES解密
	 * 先使用 key 对random进行离散，得出真正的用于解密的密钥
	 * 再使用得到的会话密钥 进行解密
	 * @param random
	 * @param key
	 * @param data
	 * @return
	 */
	public static byte[] descryptDES3ByRandom(byte[] random, byte[] key, byte[] data) {
		byte[] keyb = disperse(random, key);
		return decrypt(data, keyb);
	}
}
